package com.tticar.invmanager.common.generator;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DbType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * Created by yandou on 2018/6/14.
 */
public class MybatisPlusGenerator {

    private Logger logger = LoggerFactory.getLogger(MybatisPlusGenerator.class);
    //private String baseDir = "/Users/yandou/java/workspace/invmanager";
    private String baseDir = "F:/invmanager";
    private String outputDir = baseDir + "/src/main/java/";
    private String jsputDir = baseDir + "/src/main/resources/static/bizjs/";
    private String ftlputDir = baseDir + "/src/main/resources/templates/";
    private String xmlputDir = baseDir + "/src/main/resources/mapper/";
    private String packageName = "com.tticar.invmanager";
    //tticar
//    private String xmlputDir = baseDir + "/src/main/resources/mapper/tticar/";
//    private String packageName = "com.tticar.invmanager.tticar";

    private PackageConfig packageConfig;
    private DataSourceConfig dataSourceConfig;
    private StrategyConfig strategyConfig;
    private GlobalConfig globalConfig;

    /**
     * isJustEntity 只更新实体
     * noController 是否生成controller
     */
    private String tjson = "[\n" +
//            "  , {tname:'sys_resource',isJustEntity:false,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:true}\n" +
//            "  , {tname:'sys_department',isJustEntity:false,isController:true,isPage:true,isSearch:false,isOpt:true,isTree:true}\n" +
//            "  , {tname:'sys_user',isJustEntity:false,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:false}\n" +
//            "  , {tname:'sys_logs',isJustEntity:false,isController:true,isPage:true,isSearch:true,isOpt:false,isTree:false}\n" +
//            "  , {tname:'sys_dict',isJustEntity:false,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:true}\n" +
//            "  , {tname:'sys_role',isJustEntity:false,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:false}\n" +
//            "  , {tname:'sys_tenant',isJustEntity:false,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:false}\n" +
//            "  , {tname:'sys_tenant',isJustEntity:true,isService:false,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:false}\n" +
//            "  , {tname:'m_cateogry',isJustEntity:true,isService:false,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:true}\n" +
//            "  , {tname:'m_brand',isJustEntity:false,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:false}\n" +
//            "  , {tname:'sys_role_resource',isJustEntity:true,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:false}\n" +
//            "  , {tname:'w_wearhouse',isJustEntity:false,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:true}\n" +
//            "  , {tname:'m_cateogry_sku',isJustEntity:true,isController:false,isPage:false,isSearch:false,isOpt:false,isTree:false}\n" +
//            "  , {tname:'m_sku',isJustEntity:false,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:false}\n" +
//            "  , {tname:'m_sku_value',isJustEntity:false,isController:true,isPage:true,isSearch:false,isOpt:true,isTree:false}\n" +
//            "  , {tname:'w_relative_unit',isJustEntity:false,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:false}\n" +
//            "  , {tname:'m_materiel',isJustEntity:true,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:false}\n" +
//            "  , {tname:'m_materiel_sku',isJustEntity:true,isService:true,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:false}\n" +
//            "  , {tname:'sys_pictrue',isJustEntity:false,isService:false,isController:true,isPage:true,isSearch:false,isOpt:true,isTree:true}\n" +
//            "  , {tname:'goods',isJustEntity:false,isService:true,isController:false,isPage:true,isSearch:true,isOpt:true,isTree:true}\n" +
//            "  , {tname:'goods_production',isJustEntity:false,isService:true,isController:false,isPage:true,isSearch:true,isOpt:true,isTree:true}\n" +
//            "  , {tname:'store',isJustEntity:false,isService:true,isController:false,isPage:true,isSearch:true,isOpt:true,isTree:true}\n" +
//            "  , {tname:'w_store',isJustEntity:false,isService:false,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:false}\n" +
//            "  , {tname:'m_materiel_tticar',isJustEntity:true,isService:false,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:false}\n" +
//            "  , {tname:'pictures',isJustEntity:false,isService:true,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:false}\n" +
//            "  , {tname:'w_position',isJustEntity:false,isService:false,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:false}\n" +
//            "  , {tname:'p_purchase',isJustEntity:false,isService:false,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:false}\n" +
//           "  , {tname:'p_purchase_detail',isJustEntity:false,isService:false,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:false}\n" +
//            "  , {tname:'code_counter',isJustEntity:false,isService:false,isController:true,isPage:false,isSearch:false,isOpt:false,isTree:false}\n" +
//           "  , {tname:'p_pay',isJustEntity:false,isService:false,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:false}\n" +
//           "  , {tname:'c_check',isJustEntity:false,isService:false,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:false}\n" +
//           "  , {tname:'c_check_detail',isJustEntity:false,isService:false,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:false}\n" +
//                      "  , {tname:'m_sales_detail',isJustEntity:false,isService:false,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:false}\n" +
//                      "  , {tname:'car_brand_materiel',isJustEntity:false,isService:false,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:false}\n" +
//            "  , {tname:'store_owner',isJustEntity:false,isService:true,isController:false,isPage:true,isSearch:true,isOpt:true,isTree:true}\n" +
//                      "  , {tname:'m_cate_tmp',isJustEntity:false,isService:false,isController:true,isPage:true,isSearch:true,isOpt:true,isTree:false}\n" +
            "]";

    @Test
    public void generateCode() {
        getDataSourceConfig();
        getStrategyConfig();
        getPackageConfig();
        getGlobalConfig();

        JSONArray tbs = JSONArray.parseArray(tjson);
        generateByTables(tbs);
    }

    private void generateByTables(JSONArray models) {
        AutoGenerator mpg = new AutoGenerator();
        mpg.setTemplateEngine(new MyFreemarkerTemplateEngine());
        mpg.setDataSource(dataSourceConfig);
        mpg.setStrategy(strategyConfig);
        mpg.setPackageInfo(packageConfig);
        mpg.setGlobalConfig(globalConfig);
        mpg.setCfg(new InjectionConfig() {
            @Override
            public void initMap() {
                setMap(null);
            }
        });

        for (Object model : models) {
            mpg.setConfig(null);
            JSONObject tb = (JSONObject) model;
            mpg.getStrategy().setInclude(tb.get("tname").toString());
            logger.info("#table={}", mpg.getStrategy().getInclude()[0].toString());
            boolean isJustEntity = tb.getBoolean("isJustEntity"); //  生成entity
            boolean isService = tb.getBoolean("isService"); //生成 service/servcieImpl/mapper/xml/entity
            boolean isController = tb.getBoolean("isController"); //生成 /controller/service/servcieImpl/mapper/xml/entity
            boolean isPage = tb.getBoolean("isPage"); //生成 /ftl/controller/service/servcieImpl/mapper/xml/entity
            Map map = new HashMap();
            map.put("isTree", isPage && tb.getBoolean("isTree"));
            map.put("isSearch", isPage && tb.getBoolean("isSearch"));
            map.put("isOpt", isPage && tb.getBoolean("isOpt"));
            map.put("isService", isService);

            mpg.setCfg(new InjectionConfig() {
                @Override
                public void initMap() {
                    setMap(map);
                }
            });

            mpg.setTemplate(getTemplateConfig(isJustEntity, isService, isController));
            mpg.getCfg().setFileOutConfigList(getDefault(tb));

            mpg.execute();
        }
    }

    private TemplateConfig getTemplateConfig(boolean isJustEntity, boolean isService, boolean isController) {
        // 关闭默认 xml 生成，调整生成 至 根目录
        TemplateConfig templateConfig = new TemplateConfig();
        templateConfig.setXml(null);
        templateConfig.setEntity("/templates/temp/entity.java");
        templateConfig.setController("/templates/temp/controller.java");
        templateConfig.setService("/templates/temp/service.java");
        templateConfig.setServiceImpl("/templates/temp/serviceImpl.java");
        templateConfig.setMapper("/templates/temp/mapper.java");
        if (isJustEntity) {
            templateConfig.setController(null);
            templateConfig.setService(null);
            templateConfig.setServiceImpl(null);
            templateConfig.setMapper(null);
            return templateConfig;
        }
        if (isService) {
            templateConfig.setController(null);
            return templateConfig;
        }
        return templateConfig;
    }

    private List<FileOutConfig> getDefault(JSONObject tb) {
        boolean isJustEntity = tb.getBoolean("isJustEntity");
        boolean isService = tb.getBoolean("isService");
        boolean isController = tb.getBoolean("isController");
        boolean isPage = tb.getBoolean("isPage");

        List<FileOutConfig> focList = new ArrayList();
        if (isJustEntity) {
            return focList;
        }
        if (isService) {
            focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return xmlputDir + tableInfo.getEntityName() + "Mapper.xml";
                }
            });
            return focList;
        }

        if (!isJustEntity && !isService && isController && isPage) {
            focList.add(new FileOutConfig("/templates/temp/js.js.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return jsputDir + tableInfo.getEntityPath() + ".js";
                }
            });
            focList.add(new FileOutConfig("/templates/temp/html.ftl.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    String bpackage = ftlputDir + tableInfo.getEntityPath();
                    return bpackage + File.separator + tableInfo.getEntityPath() + ".ftl";
                }
            });
            focList.add(new FileOutConfig("/templates/temp/html_edit.ftl.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    String bpackage = ftlputDir + tableInfo.getEntityPath();
                    return bpackage + File.separator + tableInfo.getEntityPath() + "_edit.ftl";
                }
            });
        }
        return focList;
    }

    private void getGlobalConfig() {
        globalConfig = new GlobalConfig();
        globalConfig.setActiveRecord(false);
        globalConfig.setAuthor("joeyYan");
        globalConfig.setOutputDir(outputDir);
        globalConfig.setEnableCache(false);
        globalConfig.setOpen(false);
        globalConfig.setFileOverride(true);
    }

    private void getPackageConfig() {
        packageConfig = new PackageConfig();
        packageConfig.setParent(packageName);
        packageConfig.setController("controller");
    }

    private void getDataSourceConfig() {
        dataSourceConfig = new DataSourceConfig();
        dataSourceConfig.setDbType(DbType.MYSQL);
        dataSourceConfig.setUrl("jdbc:mysql://rm-uf6vsfadumd342652o.mysql.rds.aliyuncs.com/tticar_invmgr");
        dataSourceConfig.setUsername("czy");
        dataSourceConfig.setPassword("2017@Tticar");
//        dataSourceConfig.setUrl("jdbc:mysql://localhost/tticar_invmgr");
//        dataSourceConfig.setUsername("root");
////        dataSourceConfig.setPassword("");
        dataSourceConfig.setDriverName("com.mysql.jdbc.Driver");
    }

    private void getStrategyConfig() {
        strategyConfig = new StrategyConfig();
        strategyConfig.setCapitalMode(true);
        strategyConfig.setEntityLombokModel(false);
        strategyConfig.setDbColumnUnderline(true);
        strategyConfig.setNaming(NamingStrategy.underline_to_camel);
        strategyConfig.setSuperControllerClass("com.tticar.invmanager.controller.BaseController");
        strategyConfig.setEntityColumnConstant(true);
        strategyConfig.entityTableFieldAnnotationEnable(true);
        strategyConfig.setSuperEntityClass("com.tticar.invmanager.entity.BaseEntity");
        strategyConfig.setSuperEntityColumns("id", "tenant_id", "ctime", "utime");
    }
}